home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / alpha.arc / TCPIN.C < prev    next >
C/C++ Source or Header  |  1988-07-21  |  23KB  |  843 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  */
  4.  
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14.  
  15. struct tcp_stat tcp_stat;
  16.  
  17. /* This function is called from IP with the IP header in machine byte order,
  18.  * along with a mbuf chain pointing to the TCP header.
  19.  */
  20. void
  21. tcp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  22. struct mbuf *bp;    /* Data field, if any */
  23. char protocol;        /* Should always be TCP_PTCL */
  24. int32 source;        /* Remote IP address */
  25. int32 dest;        /* Our IP address */
  26. char tos;        /* Type of Service */
  27. int16 length;        /* Length of data field */
  28. char rxbroadcast;    /* Incoming broadcast - discard if true */
  29. {
  30.     void reset(),update();
  31.     void proc_syn(),send_syn(),add_reseq(),get_reseq(),unlink_tcb();
  32.  
  33.     register struct tcb *tcb;    /* TCP Protocol control block */
  34.     struct tcp seg;            /* Local copy of segment header */
  35.     struct connection conn;        /* Local copy of addresses */
  36.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  37.     int hdrlen;            /* Length of TCP header */
  38.  
  39.     if(bp == NULLBUF)
  40.         return;
  41.  
  42.     if(rxbroadcast){
  43.         /* Any TCP packet arriving as a broadcast is
  44.          * to be completely IGNORED!!
  45.          */
  46.         tcp_stat.bdcsts++;
  47.         free_p(bp);
  48.         return;
  49.     }
  50.     ph.source = source;
  51.     ph.dest = dest;
  52.     ph.protocol = protocol;
  53.     ph.length = length;
  54.     if(cksum(&ph,bp,length) != 0){
  55.         /* Checksum failed, ignore segment completely */
  56.         tcp_stat.checksum++;
  57.         free_p(bp);
  58.         return;
  59.     }
  60.     /* Form local copy of TCP header in host byte order */
  61.     if((hdrlen = ntohtcp(&seg,&bp)) < 0){
  62.         /* TCP header is too small */
  63.         tcp_stat.runt++;
  64.         free_p(bp);
  65.         return;
  66.     }
  67.     length -= hdrlen;
  68.  
  69.     /* Fill in connection structure and find TCB */
  70.     conn.local.address = dest;
  71.     conn.local.port = seg.dest;
  72.     conn.remote.address = source;
  73.     conn.remote.port = seg.source;
  74.     
  75.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  76.         struct tcb *ntcb;
  77.         void link_tcb();
  78.  
  79.         /* Check that this segment carries a SYN, and that
  80.          * there's a LISTEN on this socket with
  81.          * unspecified source address and port
  82.          */
  83.         conn.remote.address = 0;
  84.         conn.remote.port = 0;
  85.         if(!(seg.flags & SYN) || (tcb = lookup_tcb(&conn)) == NULLTCB){
  86.             /* No unspecified LISTEN either, so reject */
  87.             free_p(bp);
  88.             reset(source,dest,tos,length,&seg);
  89.             return;
  90.         }
  91.         /* We've found an server listen socket, so clone the TCB */
  92.         if(tcb->flags & CLONE){
  93.             if((ntcb = (struct tcb *)malloc(sizeof (struct tcb))) == NULLTCB){
  94.                 free_p(bp);
  95.                 /* This may fail, but we should at least try */
  96.                 reset(source,dest,tos,length,&seg);
  97.                 return;
  98.             }
  99.             ASSIGN(*ntcb,*tcb);
  100.             tcb = ntcb;
  101.             tcb->timer.arg = (char *)tcb;
  102.         } else
  103.             unlink_tcb(tcb);    /* It'll be put back on later */
  104.  
  105.         /* Stuff the foreign socket into the TCB */
  106.         tcb->conn.remote.address = source;
  107.         tcb->conn.remote.port = seg.source;
  108.  
  109.         /* NOW put on right hash chain */
  110.         link_tcb(tcb);
  111.     }
  112.     /* Do unsynchronized-state processing (p. 65-68) */
  113.     switch(tcb->state){
  114.     case CLOSED:
  115.         free_p(bp);
  116.         reset(source,dest,tos,length,&seg);
  117.         return;
  118.     case LISTEN:
  119.         if(seg.flags & RST){
  120.             free_p(bp);
  121.             return;
  122.         }
  123.         if(seg.flags & ACK){
  124.             free_p(bp);
  125.             reset(source,dest,tos,length,&seg);
  126.             return;
  127.         }
  128.         if(seg.flags & SYN){
  129.             /* (Security check is bypassed) */
  130.             /* page 66 */
  131.             tcp_stat.conin++;
  132.             proc_syn(tcb,tos,&seg);
  133.             send_syn(tcb);
  134.             setstate(tcb,SYN_RECEIVED);        
  135.             if(length != 0 || (seg.flags & FIN)) {
  136.                 break;        /* Continue processing if there's more */
  137.             }
  138.             tcp_output(tcb);
  139.         }
  140.         free_p(bp);    /* Unlikely to get here directly */
  141.         return;
  142.     case SYN_SENT:
  143.         if(seg.flags & ACK){
  144.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt)){
  145.                 free_p(bp);
  146.                 reset(source,dest,tos,length,&seg);
  147.                 return;
  148.             }
  149.         }
  150.         if(seg.flags & RST){    /* p 67 */
  151.             if(seg.flags & ACK){
  152.                 /* The ack must be acceptable since we just checked it.
  153.                  * This is how the remote side refuses connect requests.
  154.                  */
  155.                 close_self(tcb,RESET);
  156.             }
  157.             free_p(bp);
  158.             return;
  159.         }
  160.         /* (Security check skipped here) */
  161.         /* Check incoming precedence; it must match if there's an ACK */
  162.         if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){
  163.             free_p(bp);
  164.             reset(source,dest,tos,length,&seg);
  165.             return;
  166.         }
  167.         if(seg.flags & SYN){
  168.             proc_syn(tcb,tos,&seg);
  169.             if(seg.flags & ACK){
  170.                 /* Our SYN has been acked, otherwise the ACK
  171.                  * wouldn't have been valid.
  172.                  */
  173.                 update(tcb,&seg);
  174.                 setstate(tcb,ESTABLISHED);
  175.             } else {
  176.                 setstate(tcb,SYN_RECEIVED);
  177.             }
  178.             if(length != 0 || (seg.flags & FIN)) {
  179.                 break;        /* Continue processing if there's more */
  180.             }
  181.             tcp_output(tcb);
  182.         } else {
  183.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  184.         }
  185.         return;
  186.     }
  187.     /* We reach this point directly in any synchronized state. Note that
  188.      * if we fell through from LISTEN or SYN_SENT processing because of a
  189.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  190.      */
  191.  
  192.     /* Trim segment to fit receive window. */
  193.     if(trim(tcb,&seg,&bp,&length) == -1){
  194.         /* Segment is unacceptable */
  195.         if(!(seg.flags & RST)){
  196.             tcb->flags |= FORCE;
  197.             tcp_output(tcb);
  198.         }
  199.         return;
  200.     }
  201.     /* If segment isn't the next one expected, and there's data
  202.      * or flags associated with it, put it on the resequencing
  203.      * queue, ACK it and return.
  204.      *
  205.      * Processing the ACK in an out-of-sequence segment without
  206.      * flags or data should be safe, however.
  207.      */
  208.     if(seg.seq != tcb->rcv.nxt
  209.      && (length != 0 || (seg.flags & (SYN|FIN)) )){
  210.         add_reseq(tcb,tos,&seg,bp,length);
  211.         tcb->flags |= FORCE;
  212.         tcp_output(tcb);
  213.         return;
  214.     }
  215.     /* This loop first processes the current segment, and then
  216.      * repeats if it can process the resequencing queue.
  217.      */
  218.     for(;;){
  219.         /* We reach this point with an acceptable segment; all data and flags
  220.          * are in the window, and the starting sequence number equals rcv.nxt
  221.          * (p. 70)
  222.          */    
  223.         if(seg.flags & RST){
  224.             if(tcb->state == SYN_RECEIVED
  225.              && !(tcb->flags & (CLONE|ACTIVE))){
  226.                 /* Go back to listen state only if this was
  227.                  * not a cloned or active server TCB
  228.                  */
  229.                 setstate(tcb,LISTEN);
  230.             } else {
  231.                 close_self(tcb,RESET);
  232.             }
  233.             free_p(bp);
  234.             return;
  235.         }
  236.         /* (Security check skipped here) p. 71 */
  237.         /* Check for precedence mismatch or erroneous extra SYN */
  238.         if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
  239.             free_p(bp);
  240.             reset(source,dest,tos,length,&seg);
  241.             return;
  242.         }
  243.         /* Check ack field p. 72 */
  244.         if(!(seg.flags & ACK)){
  245.             free_p(bp);    /* All segments after synchronization must have ACK */
  246.             return;
  247.         }
  248.         /* Process ACK */
  249.         switch(tcb->state){
  250.         case SYN_RECEIVED:
  251.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  252.                 update(tcb,&seg);
  253.                 setstate(tcb,ESTABLISHED);
  254.             } else {
  255.                 free_p(bp);
  256.                 reset(source,dest,tos,length,&seg);
  257.                 return;
  258.             }
  259.             break;
  260.         case ESTABLISHED:
  261.         case CLOSE_WAIT:
  262.             update(tcb,&seg);
  263.             break;
  264.         case FINWAIT1:    /* p. 73 */
  265.             update(tcb,&seg);
  266.             if(tcb->sndcnt == 0){
  267.                 /* Our FIN is acknowledged */
  268.                 setstate(tcb,FINWAIT2);
  269.             }
  270.             break;
  271.         case FINWAIT2:
  272.             update(tcb,&seg);
  273.             break;
  274.         case CLOSING:
  275.             update(tcb,&seg);
  276.             if(tcb->sndcnt == 0){
  277.                 /* Our FIN is acknowledged */
  278.                 setstate(tcb,TIME_WAIT);
  279.                 tcb->timer.start = MSL2 * (1000 / MSPTICK);
  280.                 start_timer(&tcb->timer);
  281.             }
  282.             break;
  283.         case LAST_ACK:
  284.             update(tcb,&seg);
  285.             if(tcb->sndcnt == 0){
  286.                 /* Our FIN is acknowledged, close connection */
  287.                 close_self(tcb,NORMAL);
  288.                 return;
  289.             }            
  290.         case TIME_WAIT:
  291.             tcb->flags |= FORCE;
  292.             start_timer(&tcb->timer);
  293.         }
  294.  
  295.         /* (URGent bit processing skipped here) */
  296.  
  297.         /* Process the segment text, if any, beginning at rcv.nxt (p. 74) */
  298.         if(length != 0){
  299.             switch(tcb->state){
  300.             case SYN_RECEIVED:
  301.             case ESTABLISHED:
  302.             case FINWAIT1:
  303.             case FINWAIT2:
  304.                 /* Place on receive queue */
  305.                 append(&tcb->rcvq,bp);
  306.                 tcb->rcvcnt += length;
  307.                 tcb->rcv.nxt += length;
  308.                 tcb->rcv.wnd -= length;
  309.                 tcb->flags |= FORCE;
  310.                 break;
  311.             default:
  312.                 /* Ignore segment text */
  313.                 free_p(bp);
  314.                 break;
  315.             }
  316.         }
  317.         /* If the user has set up a r_upcall function and there's
  318.          * data to be read, notify him.
  319.          *
  320.          * This is done before sending an acknowledgement,
  321.          * to give the user a chance to piggyback some reply data.
  322.          * It's also done before processing FIN so that the state
  323.          * change upcall will occur after the user has had a chance
  324.          * to read the last of the incoming data.
  325.          */
  326.         if(tcb->r_upcall && tcb->rcvcnt != 0){
  327.             (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  328.         }
  329.         /* process FIN bit (p 75) */
  330.         if(seg.flags & FIN){
  331.             tcb->flags |= FORCE;    /* Always respond with an ACK */
  332.  
  333.             switch(tcb->state){
  334.             case SYN_RECEIVED:
  335.             case ESTABLISHED:
  336.                 tcb->rcv.nxt++;
  337.                 setstate(tcb,CLOSE_WAIT);
  338.                 break;
  339.             case FINWAIT1:
  340.                 tcb->rcv.nxt++;
  341.                 if(tcb->sndcnt == 0){
  342.                     /* Our FIN has been acked; bypass CLOSING state */
  343.                     setstate(tcb,TIME_WAIT);
  344.                     tcb->timer.start = MSL2 * (1000/MSPTICK);
  345.                     start_timer(&tcb->timer);
  346.                 } else {
  347.                     setstate(tcb,CLOSING);
  348.                 }
  349.                 break;
  350.             case FINWAIT2:
  351.                 tcb->rcv.nxt++;
  352.                 setstate(tcb,TIME_WAIT);
  353.                 tcb->timer.start = MSL2 * (1000/MSPTICK);
  354.                 start_timer(&tcb->timer);
  355.                 break;
  356.             case CLOSE_WAIT:
  357.             case CLOSING:
  358.             case LAST_ACK:
  359.                 break;        /* Ignore */
  360.             case TIME_WAIT:    /* p 76 */
  361.                 start_timer(&tcb->timer);
  362.                 break;
  363.             }
  364.         }
  365.         /* Scan the resequencing queue, looking for a segment we can handle,
  366.          * and freeing all those that are now obsolete.
  367.          */
  368.         while(tcb->reseq != NULLRESEQ && seq_ge(tcb->rcv.nxt,tcb->reseq->seg.seq)){
  369.             get_reseq(tcb,&tos,&seg,&bp,&length);
  370.             if(trim(tcb,&seg,&bp,&length) == 0)
  371.                 goto gotone;
  372.             /* Segment is an old one; trim has freed it */
  373.         }
  374.         break;
  375. gotone:    ;
  376.     }
  377.     tcp_output(tcb);    /* Send any necessary ack */
  378. }
  379.  
  380. /* Process an incoming ICMP response */
  381. tcp_icmp(source,dest,type,code,bpp)
  382. int32 source;            /* Original IP datagram source (i.e. us) */
  383. int32 dest;            /* Original IP datagram dest (i.e., them) */
  384. char type,code;            /* ICMP error codes */
  385. struct mbuf **bpp;        /* First 8 bytes of TCP header */
  386. {
  387.     struct tcp seg;
  388.     struct connection conn;
  389.     register struct tcb *tcb;
  390.  
  391.     /* Extract the socket info from the returned TCP header fragment
  392.      * Note that since this is a datagram we sent, the source fields
  393.      * refer to the local side.
  394.      */
  395.     ntohtcp(&seg,bpp);
  396.     conn.local.port = seg.source;
  397.     conn.remote.port = seg.dest;
  398.     conn.local.address = source;
  399.     conn.remote.address = dest;
  400.     if((tcb = lookup_tcb(&conn)) == NULLTCB)
  401.         return;    /* Unknown connection, ignore */
  402.  
  403.     /* Verify that the sequence number in the returned segment corresponds
  404.      * to something currently unacknowledged. If not, it can safely
  405.      * be ignored.
  406.      */
  407.     if(!seq_within(seg.seq,tcb->snd.una,tcb->snd.nxt))
  408.         return;
  409.  
  410.     /* The strategy here is that Destination Unreachable and Time Exceeded
  411.      * messages that occur after a connection has been established are likely
  412.      * to be transient events, and shouldn't kill our connection (at least
  413.      * until after we've tried a few more times). On the other hand, if
  414.      * they occur on our very first attempt to send a datagram on a new
  415.      * connection, they're probably "for real". In any event, the info
  416.      * is saved.
  417.      */
  418.     switch(uchar(type)){
  419.     case DEST_UNREACH:
  420.     case TIME_EXCEED:
  421.         tcb->type = type;
  422.         tcb->code = code;
  423.         if(tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED){
  424.             close_self(tcb,NETWORK);
  425.         }
  426.         break;
  427.     case QUENCH:
  428.         /* Source quench; cut the congestion window in half,
  429.          * but don't let it go below one packet
  430.          */
  431.         tcb->cwind /= 2;
  432.         tcb->cwind = max(tcb->mss,tcb->cwind);
  433.         break;
  434.     }
  435. }
  436. /* Send an acceptable reset (RST) response for this segment
  437.  * The RST reply is composed in place on the input segment
  438.  */
  439. static void
  440. reset(source,dest,tos,length,seg)
  441. int32 source;            /* Remote IP address */
  442. int32 dest;            /* Our IP address */
  443. char tos;            /* Type of Service */
  444. int16 length;            /* Length of data portion */
  445. register struct tcp *seg;    /* Offending TCP header */
  446. {
  447.     struct mbuf *hbp;
  448.     struct pseudo_header ph;
  449.     int16 tmp;
  450.     char rflags;
  451.  
  452.     if(seg->flags & RST)
  453.         return;    /* Never send an RST in response to an RST */
  454.  
  455.     tcp_stat.resets++;
  456.  
  457.     /* Compose the RST IP pseudo-header, swapping addresses */
  458.     ph.source = dest;
  459.     ph.dest = source;
  460.     ph.protocol = TCP_PTCL;
  461.     ph.length = TCPLEN;
  462.  
  463.     /* Swap port numbers */
  464.     tmp = seg->dest;
  465.     seg->dest = seg->source;
  466.     seg->source = tmp;
  467.  
  468.     rflags = RST;
  469.     if(seg->flags & ACK){
  470.         /* This reset is being sent to clear a half-open connection.
  471.          * Set the sequence number of the RST to the incoming ACK
  472.          * so it will be acceptable.
  473.          */
  474.         seg->seq = seg->ack;
  475.         seg->ack = 0;
  476.     } else {
  477.         /* We're rejecting a connect request (SYN) from LISTEN state
  478.          * so we have to "acknowledge" their SYN.
  479.          */
  480.         rflags |= ACK;
  481.         seg->ack = seg->seq;
  482.         seg->seq = 0;
  483.         if(seg->flags & SYN)
  484.             seg->ack++;
  485.         seg->ack += length;
  486.         if(seg->flags & FIN)
  487.             seg->ack++;
  488.     }
  489.     seg->flags = rflags;
  490.     seg->wnd = 0;
  491.     seg->up = 0;
  492.     seg->mss = 0;
  493.     if((hbp = htontcp(seg,NULLBUF,&ph)) == NULLBUF)
  494.         return;
  495.     /* Ship it out (note swap of addresses) */
  496.     ip_send(dest,source,TCP_PTCL,tos,0,hbp,ph.length,0,0);
  497. }
  498.  
  499. /* Process an incoming acknowledgement and window indication.
  500.  * From page 72.
  501.  */
  502. static void
  503. update(tcb,seg)
  504. register struct tcb *tcb;
  505. register struct tcp *seg;
  506. {
  507.     int16 acked;
  508.     int16 expand;
  509.  
  510.     acked = 0;
  511.     if(seq_gt(seg->ack,tcb->snd.nxt)){
  512.         tcb->flags |= FORCE;    /* Acks something not yet sent */
  513.         return;
  514.     }
  515.     /* Decide if we need to do a window update.
  516.      * This is always checked whenever a legal ACK is received,
  517.      * even if it doesn't actually acknowledge anything,
  518.      * because it might be a spontaneous window reopening.
  519.      */
  520.     if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1) 
  521.      && seq_ge(seg->ack,tcb->snd.wl2))){
  522.         /* If the window had been closed, crank back the
  523.          * send pointer so we'll immediately resume transmission.
  524.          * Otherwise we'd have to wait until the next probe.
  525.          */
  526.         if(tcb->snd.wnd == 0 && seg->wnd != 0)
  527.             tcb->snd.ptr = tcb->snd.una;
  528.         tcb->snd.wnd = seg->wnd;
  529.         tcb->snd.wl1 = seg->seq;
  530.         tcb->snd.wl2 = seg->ack;
  531.     }
  532.     /* See if anything new is being acknowledged */
  533.     if(!seq_gt(seg->ack,tcb->snd.una))
  534.         return;    /* Nothing more to do */
  535.  
  536.     /* We're here, so the ACK must have actually acked something */
  537.     acked = seg->ack - tcb->snd.una;
  538.  
  539.     /* Expand congestion window if not already at limit */
  540.     if(tcb->cwind < tcb->snd.wnd){
  541.         if(tcb->cwind < tcb->ssthresh){
  542.             /* Still doing slow start/CUTE, expand by amount acked */
  543.             expand = min(acked,tcb->mss);
  544.         } else {
  545.             /* Steady-state test of extra path capacity */
  546.             expand = ((long)tcb->mss * tcb->mss) / tcb->cwind;
  547.         }
  548.         /* Guard against arithmetic overflow */
  549.         if(tcb->cwind + expand < tcb->cwind)
  550.             expand = MAXINT16 - tcb->cwind;
  551.  
  552.         /* Don't expand beyond the offered window */
  553.         if(tcb->cwind + expand > tcb->snd.wnd)
  554.             expand = tcb->snd.wnd - tcb->cwind;
  555.  
  556.         if(expand != 0){
  557. #ifdef    notdef
  558.             /* Kick up the mean deviation estimate to prevent
  559.              * unnecessary retransmission should we already be
  560.              * bandwidth limited
  561.              */
  562.             tcb->mdev += ((long)tcb->srtt * expand) / tcb->cwind;
  563. #endif
  564.             tcb->cwind += expand;
  565.         }
  566.     }
  567.     /* Round trip time estimation */
  568.     if(run_timer(&tcb->rtt_timer) && seq_ge(seg->ack,tcb->rttseq)){
  569.         /* A timed sequence number has been acked */
  570.         stop_timer(&tcb->rtt_timer);
  571.         if(!(tcb->flags & RETRAN)){
  572.             int32 rtt;    /* measured round trip time */
  573.             int32 abserr;    /* abs(rtt - srtt) */
  574.  
  575.             /* This packet was sent only once and now
  576.              * it's been acked, so process the round trip time
  577.              */
  578.             rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
  579.             rtt *= MSPTICK;        /* milliseconds */
  580.  
  581.             /* If this ACKs our SYN, this is the first ACK
  582.              * we've received; base our entire SRTT estimate
  583.              * on it. Otherwise average it in with the prior
  584.              * history, also computing mean deviation.
  585.              */
  586.             if(rtt > tcb->srtt &&
  587.              (tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED)){
  588.                 tcb->srtt = rtt;
  589.             } else {
  590.                 abserr = (rtt > tcb->srtt) ? rtt - tcb->srtt : tcb->srtt - rtt;
  591.                 tcb->srtt = ((AGAIN-1)*tcb->srtt + rtt) / AGAIN;
  592.                 tcb->mdev = ((DGAIN-1)*tcb->mdev + abserr) / DGAIN;
  593.             }
  594.             /* Reset the backoff level */
  595.             tcb->backoff = 0;
  596.         }
  597.     }
  598.     /* If we're waiting for an ack of our SYN, note it and adjust count */
  599.     if(!(tcb->flags & SYNACK)){
  600.         tcb->flags |= SYNACK;
  601.         acked--;
  602.         tcb->sndcnt--;
  603.     }
  604.     /* Remove acknowledged bytes from the send queue and update the
  605.      * unacknowledged pointer. If a FIN is being acked,
  606.      * pullup won't be able to remove it from the queue.
  607.      */
  608.     pullup(&tcb->sndq,NULLCHAR,acked);
  609.  
  610.     /* This will include the FIN if there is one */
  611.     tcb->sndcnt -= acked;
  612.     tcb->snd.una = seg->ack;
  613.  
  614.     /* Stop retransmission timer, but restart it if there is still
  615.      * unacknowledged data.
  616.      */    
  617.     stop_timer(&tcb->timer);
  618.     if(tcb->snd.una != tcb->snd.nxt)
  619.         start_timer(&tcb->timer);
  620.  
  621.     /* If retransmissions have been occurring, make sure the
  622.      * send pointer doesn't repeat ancient history
  623.      */
  624.     if(seq_lt(tcb->snd.ptr,tcb->snd.una))
  625.         tcb->snd.ptr = tcb->snd.una;
  626.  
  627.     /* Clear the retransmission flag since the oldest
  628.      * unacknowledged segment (the only one that is ever retransmitted)
  629.      * has now been acked.
  630.      */
  631.     tcb->flags &= ~RETRAN;
  632.  
  633.     /* If outgoing data was acked, notify the user so he can send more
  634.      * unless we've already sent a FIN.
  635.      */
  636.     if(acked != 0 && tcb->t_upcall){
  637.         switch(tcb->state){
  638.          case ESTABLISHED:
  639.         case CLOSE_WAIT:
  640.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  641.         }
  642.     }
  643. }
  644.  
  645. /* Determine if the given sequence number is in our receiver window.
  646.  * NB: must not be used when window is closed!
  647.  */
  648. static
  649. int
  650. in_window(tcb,seq)
  651. struct tcb *tcb;
  652. int32 seq;
  653. {
  654.     return seq_within(seq,tcb->rcv.nxt,(int32)(tcb->rcv.nxt+tcb->rcv.wnd-1));
  655. }
  656.  
  657. /* Process an incoming SYN */
  658. static void
  659. proc_syn(tcb,tos,seg)
  660. register struct tcb *tcb;
  661. char tos;
  662. struct tcp *seg;
  663. {
  664.     int16 mtu,ip_mtu();
  665.  
  666.     tcb->flags |= FORCE;    /* Always send a response */
  667.  
  668.     /* Note: It's not specified in RFC 793, but SND.WL1 and
  669.      * SND.WND are initialized here since it's possible for the
  670.      * window update routine in update() to fail depending on the
  671.      * IRS if they are left unitialized.
  672.      */
  673.     /* Check incoming precedence and increase if higher */
  674.     if(PREC(tos) > PREC(tcb->tos))
  675.         tcb->tos = tos;
  676.     tcb->rcv.nxt = seg->seq + 1;    /* p 68 */
  677.     tcb->snd.wl1 = tcb->irs = seg->seq;
  678.     tcb->snd.wnd = seg->wnd;
  679.     if(seg->mss != 0)
  680.         tcb->mss = seg->mss;
  681.     /* Check the MTU of the interface we'll use to reach this guy
  682.      * and lower the MSS so that unnecessary fragmentation won't occur
  683.      */
  684.     if((mtu = ip_mtu(tcb->conn.remote.address)) != 0){
  685.         /* Allow space for the TCP and IP headers */
  686.         mtu -= TCPLEN + IPLEN;
  687.         tcb->cwind = tcb->mss = min(mtu,tcb->mss);
  688.     }
  689. }
  690.  
  691. /* Generate an initial sequence number and put a SYN on the send queue */
  692. void
  693. send_syn(tcb)
  694. register struct tcb *tcb;
  695. {
  696.     tcb->iss = iss();
  697.     tcb->rttseq = tcb->snd.wl2 = tcb->snd.una = tcb->iss;
  698.     tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq;
  699.     tcb->sndcnt++;
  700.     tcb->flags |= FORCE;
  701. }
  702.  
  703. /* Add an entry to the resequencing queue in the proper place */
  704. static void
  705. add_reseq(tcb,tos,seg,bp,length)
  706. struct tcb *tcb;
  707. char tos;
  708. struct tcp *seg;
  709. struct mbuf *bp;
  710. int16 length;
  711. {
  712.     register struct reseq *rp,*rp1;
  713.  
  714.     /* Allocate reassembly descriptor */
  715.     if((rp = (struct reseq *)malloc(sizeof (struct reseq))) == NULLRESEQ){
  716.         /* No space, toss on floor */
  717.         free_p(bp);
  718.         return;
  719.     }
  720.     ASSIGN(rp->seg,*seg);
  721.     rp->tos = tos;
  722.     rp->bp = bp;
  723.     rp->length = length;
  724.  
  725.     /* Place on reassembly list sorting by starting seq number */
  726.     rp1 = tcb->reseq;
  727.     if(rp1 == NULLRESEQ || seq_lt(seg->seq,rp1->seg.seq)){
  728.         /* Either the list is empty, or we're less than all other
  729.          * entries; insert at beginning.
  730.          */
  731.         rp->next = rp1;
  732.         tcb->reseq = rp;
  733.     } else {
  734.         /* Find the last entry less than us */
  735.         for(;;){
  736.             if(rp1->next == NULLRESEQ || seq_lt(seg->seq,rp1->next->seg.seq)){
  737.                 /* We belong just after this one */
  738.                 rp->next = rp1->next;
  739.                 rp1->next = rp;
  740.                 break;
  741.             }
  742.             rp1 = rp1->next;
  743.         }
  744.     }
  745. }
  746.  
  747. /* Fetch the first entry off the resequencing queue */
  748. static void
  749. get_reseq(tcb,tos,seg,bp,length)
  750. register struct tcb *tcb;
  751. char *tos;
  752. struct tcp *seg;
  753. struct mbuf **bp;
  754. int16 *length;
  755. {
  756.     register struct reseq *rp;
  757.  
  758.     if((rp = tcb->reseq) == NULLRESEQ)
  759.         return;
  760.  
  761.     tcb->reseq = rp->next;
  762.  
  763.     *tos = rp->tos;
  764.     ASSIGN(*seg,rp->seg);
  765.     *bp = rp->bp;
  766.     *length = rp->length;
  767.     free((char *)rp);
  768. }
  769.  
  770. /* Trim segment to fit window. Return 0 if OK, -1 if segment is
  771.  * unacceptable.
  772.  */
  773. static int
  774. trim(tcb,seg,bp,length)
  775. register struct tcb *tcb;
  776. register struct tcp *seg;
  777. struct mbuf **bp;
  778. int16 *length;
  779. {
  780.     struct mbuf *nbp;
  781.     long dupcnt,excess;
  782.     int16 len;        /* Segment length including flags */
  783.     char accept;
  784.  
  785.     accept = 0;
  786.     len = *length;
  787.     if(seg->flags & SYN)
  788.         len++;
  789.     if(seg->flags & FIN)
  790.         len++;
  791.  
  792.     /* Acceptability tests */
  793.     if(tcb->rcv.wnd == 0){
  794.         /* Only in-order, zero-length segments are acceptable when our window
  795.          * is closed.
  796.          */
  797.         if(seg->seq == tcb->rcv.nxt && len == 0){
  798.             return 0;    /* Acceptable, no trimming needed */
  799.         }
  800.     } else {
  801.         /* Some part of the segment must be in the window */
  802.         if(in_window(tcb,seg->seq)){
  803.             accept++;    /* Beginning is */
  804.         } else if(len != 0){
  805.             if(in_window(tcb,(int32)(seg->seq+len-1)) || /* End is */
  806.              seq_within(tcb->rcv.nxt,seg->seq,(int32)(seg->seq+len-1))){ /* Straddles */
  807.                 accept++;
  808.             }
  809.         }
  810.     }
  811.     if(!accept){
  812.         free_p(*bp);
  813.         return -1;
  814.     }
  815.     dupcnt = tcb->rcv.nxt - seg->seq;
  816.     if(dupcnt > 0){
  817.         tcb->rerecv += dupcnt;
  818.         /* Trim off SYN if present */
  819.         if(seg->flags & SYN){
  820.             /* SYN is before first data byte */
  821.             seg->flags &= ~SYN;
  822.             seg->seq++;
  823.             dupcnt--;
  824.         }
  825.         if(dupcnt > 0){
  826.             pullup(bp,NULLCHAR,(int16)dupcnt);
  827.             seg->seq += dupcnt;
  828.             *length -= dupcnt;
  829.         }
  830.     }
  831.     excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
  832.     if(excess > 0){
  833.         tcb->rerecv += excess;
  834.         /* Trim right edge */
  835.         *length -= excess;
  836.         nbp = copy_p(*bp,*length);
  837.         free_p(*bp);
  838.         *bp = nbp;
  839.         seg->flags &= ~FIN;    /* FIN follows last data byte */
  840.     }
  841.     return 0;
  842. }
  843.